#!/usr/bin/python
####################################################################################
####################################################################################
##      Author: Ahmed Adel Mohamed
##      Date: 27/04/2011
##      Version: 1.0.4
##      Puropse:
##              Script to arrange Cisco Access list by 
##              Number of hits, it has one argument 
##              which is the access-list file name
##          
##   Copyright (C) 2011  Ahmed Adel
##
##   This program is free software: you can redistribute it and/or modify
##   it under the terms of the GNU General Public License as published by
##   the Free Software Foundation, either version 3 of the License, or
##      (at your option) any later version.
##
##   This program is distributed in the hope that it will be useful,
##   but WITHOUT ANY WARRANTY; without even the implied warranty of
##   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
##   GNU General Public License for more details.
##
##   You should have received a copy of the GNU General Public License
##   along with this program.  If not, see <http://www.gnu.org/licenses/>.
####################################################################################
####################################################################################
# Import Modules
import string
import re
import sys
import getopt

# Function that arranges the access list lines and output top 5 lines
def arrange_list(list, order, line_number):
    line_number = int(line_number) - 1
    if order == 'r':
        list.sort(key=lambda arr: arr[0], reverse=False);
    else:
        list.sort(key=lambda arr: arr[0], reverse=True);
    count = 0
    for templine in list:
        templine.pop(0)
        print(' '.join(templine))
        if count == int(line_number):
            break
        count += 1
    return;
	
# check if access list filename is passed as argument
order = 0
if len(sys.argv) < 2:
        print("!!!!!! please enter the access-list file name !!!!!!")
        sys.exit()
else:
        optlist, args = getopt.getopt(sys.argv[1:], 'rl:')
        for o, a in optlist:
		if o == "-l":
			line_number = a
		else:
			line_number = 5
		if o == "-r":
			order = "r"
	
	access_file = args[0]
	
# Open access list file to read access list lines
Input = open(access_file, "r")

# define Regular expressoin variables used in access list comparisons
reg1 = re.compile("hitcnt")
reg2 = re.compile("inactive")
reg3 = re.compile("nat0", re.IGNORECASE)
regnum = re.compile('\d+')

# Define array
access_list =[]
Lines = Input.readlines()

# Get the first access list name
for line in Lines:
        if reg1.search(line):
                temp = line.split()
                access_list_name = temp[1]
                break

# Loop on access lists
for line in Lines:
                # Ignore access list lines which are inactive or used for nat
        if reg2.search(line) or reg3.search(line):
                continue
                # Arrange only access list lines which have hit count
        elif reg1.search(line):
                access_line = line.split()
                if access_line[1] == access_list_name:
                        hitcnt = int(regnum.search(access_line[len(access_line)-2]).group())
                        access_line.insert(0,hitcnt)
                        access_list.append(access_line)
                                # Change access list name 
                else:
                        access_list_name = access_line[1]
                        # call function to get the values of the array, arrange the access-list by number of hits and print top 5 lines
                        arrange_list(access_list, order, line_number)
                        print("\n\n\n")
                        del access_list[:]
                        hitcnt = int(regnum.search(access_line[len(access_line)-2]).group())
                        access_line.insert(0,hitcnt)
                        access_list.append(access_line)
arrange_list(access_list, order, line_number)
Input.close()
